home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 24
/
CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso
/
CUCD
/
Utilities
/
HWGPOST
/
hwgpostlib.doc
< prev
next >
Wrap
Text File
|
1996-10-26
|
23KB
|
561 lines
PostScript shared library interface (post.library, with HWGPOST >= V22.26)
==========================================================================
HWGPOST, Copyright 1993-96 Heinz Wrobel, is mostly calling
compatible to Post V1.7, Copyright Adrian Aylward 1991, 1992. But it
is a very different beast inside.
This document is derived from Adrian Aylward's post.library
documentation. It contains many comments on HWGPOST, developers should
read, especially those developers who are familiar with the old
post.library 1.7.
Introduction
============
The file "post.library" is an AmigaOS Exec shared library containing a
mostly Level II compliant PostScript interpreter. It is designed to
be shareable between different processes, supporting arbitrarily many
PostScript activations - at least until you run out of memory.
This file should be read in conjunction with the header file
"postlib.h".
The standard user interface source files are distributed with the old
Post 1.7. Read them as examples for now. If there is different
information in this document or the current headerfile postlib.h or
init.ps, the current information holds.
Activation Records
==================
Simultaneous multiple activations of PostScript are allowed. Before
using post.library you must first open it by a call to OpenLibrary().
To create an activation you then call PScreateact() which returns a
pointer to the activation record. You can then make calls to the
interpreter library, passing the activation record pointer as an
argument. You can create several activations, possibly from different
processes and intermingle the interpreter calls if you wish. But you
CANNOT PASS ACTIVATION RECORDS BETWEEN PROCESSES! When you have
finished with an activation, call PSdeleteact() to delete it and free
the memory it used. Do not free bitmap memory or filehandles before
freeing the activation record! When you have finished with the library
call CloseLibrary(); if no other processes have it open, then Exec can
remove it from memory if the space is needed.
N.B. the library can only be called from a process, as it calls
various AmigaDOS functions. IT IS NOT PERMISSIBLE TO PASS ACTIVATION
RECORDS BETWEEN PROCESSES! NOTE THIS WELL!
The Parameter Block
===================
The parameter block is the argument to PScreateact(). It specifies
the addresses of the bitmap planes, size of the page, and the amount
of memory to be allocated for the activation etc ... Its format is
defined in detail in the header file postlib.h.
N.B. all ints are 32 bits, shorts are 16 bits.
The page size is limited to 30000 pixels a side. The densities
(pixels per inch) may be any strictly positive integer value. The y
direction may be set to +1 - if the bitmap rows are in PostScript
order (bottom row first) or -1 - Amiga order (top row first).
page.buf[24] Bitplane pointers, up to 24
page.len Size in bytes of each plane
page.depth Number plane pointers to use
page.flags Special device options
page.bitspercolor How many plane pointers to be used per gun.
page.PSextdevice An optional extension to the device information
page.xbytes Number of bytes in each row
page.xsize Number of pixels in each row
page.ysize Number of rows
page.ybase Base of current band
page.yheight Total height of full page, for band rendering
page.xden X density
page.yden Y density
page.ydir Y direction
To specify how many bitplanes are used per color, you set
"bitspercolor" to the appropriate value. If this value is not set, one
bitplane per color is assumed and only 1, 3, and 4 are permissible as
depth in this case. Example: RGB 3:3:2 => depth=8, bitspercolor=3.
The amount of colors, i.e. the basic colorspace used by the
interpreter is determined by depth and bitspercolor. The "logical"
colordepth derived from these values may be 1, 3, or 4,
representing B&W, RGB, RGBW/CMYK, respectively.
Note that bitspercolor should not exceed 8.
For special use, the page device description can be enhanced by
setting page.PSextdevice. The PSextdevice structure
currently contains the following fields.
flags Extension of the main flags field.
maskbuf If set, must be a plane as in page.buf. For
any rendering you'll get bits set in this mask
plane. This gives you a mask of the actually
used places in the buffer. The mask might be
useful for BltMaskBitMapRastPort() or some
such. erasepage will clear this mask plane.
Kbuf[8] Eight additional plane pointers to allow for
true eight bit CMYK rendering. You need to set
the depth to a value greater 24 for these to
be used.
The length of these structures is subject to change. Always set unused
fields to zero.
As a starting point for memory sizes try the values following. (These
are defined in the header file.) For normal PostScript programs the
defaults are perfectly satisfactory. If you specify a value of zero
the default will be used instead; values less than the minimum will be
increased.
memvlen 50000 VM
memflen 60000 Font cache
memllen 15000 Path lines
memhlen 20000 Halftones
memplen 60000 Pattern cache
The user data pointer is intended to be used to identify multiple
activations. You can set it to any value you like. The function
pointers are described below.
userdata User data pointer
flushfunc Flush page function pointer
copyfunc Copy page function pointer
The standard input and output streams are the AmigaDOS file handles to
be used by the interpreter for %stdin, %stdout, %stderr. Also the
standard output is used for prompts and the error output for error
messages. These file handles will not be closed by the interpreter
even though PostScript file objects referring to them may be closed.
You should not set them to NULL/ZERO. If you don't need any input
or output, set up valid NIL: filehandles!
infh Standard Input file handle
outfh Standard Output file handle
errfh Standard Error file handle
These are for backwards compatibility with the infamous "callextfunc"
operator. You'll find details below. It is recommended that you
don't touch these in new code.
funcmax Number of external functions
functab Pointer to external function table, or zero
Anything else in the block is reserved and must be set to zero.
Notes on the special device flags
---------------------------------
In the header file "postlib.h" you will find some flag definitions for
the main flag field of the parameter page. They need more explanation.
HWGPOST_DEVx_NOSHADE
Halftoning is in effect suppressed. No halftone screens will
be used. Any color intensity that would cause shading will be
rendered as the next lower color value truly representable
within the bitplanes would. Shading is simply turned off.
This increases rendering speed.
HWGPOST_DEVx_CMYK
post.library supports the CMYK color space and operators.
When converting any colors to values passed to the transfer
functions, it creates RGBW values, though, instead of CMYK.
With this flag set, the colorspace mapping algorithm will stay
with CMYK and CMYK will be passed to the transfer functions if
applicable.
HWGPOST_DEVx_INVERTOUTPUT
The output of the transfer functions represent the value that
should be rendered into the bitplanes. With this flag set,
these values in the range [0.0;1.0] will effectively reversed
with a simple "shade = 1.0 - shade" before the rendering is
set up. This is the easiest way to create "negative" output
and might come in handy for multiple bitplane color handling,
where black should be "all bits 0" instead of "all bits 1" in
the planes. This is good for true color rendering.
Function Pointers
=================
There are two function pointers within the parameter block, which are
used when the interpreter needs to call routines supplied by its
client. If the pointers are NULL, the calls are skipped.
To help identify calls from multiple activations, the activation
record address is also passed in A0 and the userdata pointer in A1.
flushfunc(D0: int y1, D1: int y2)
Flush the bitmap to the screen. The interpreter calls this function
after a painting operation has updated the bitmap. Then if the output
is being viewed interactively the client can update the screen or
window. The arguments are the range of bitmap rows (y1 ... y2-1) that
may have been updated.
copyfunc(D0: int num)
Copy the page to the output device. The argument is the value of
"#copies", which should be taken into account if the output is to a
printer, but is not meaningful for screen output. You should take a
look at the description for PSsignalint() below, too.
Calling External Functions
==========================
The original "callextfunc" operator of post.library <= V1.7 is no
longer supported even though it is currently still available in
disguise as "@callextfunc". Use of this operator is strongly
discouraged as it might lure you into making assumptions about
internal HWGPOST data representations.
A more general way to call external functions has been devised via the
new "@calluserhook" operator. This operator collects the arguments,
passes them to a "Hook" as defined by the utility.library, records any
changes and returns the result. This is the calling sequence:
mark <args..> <userhookadr> <msgadr> @calluserhook
On return the operand stack will look like this:
mark <args..> <resint>
A number from zero to eight arguments is supported. Only certain
PostScript objects may be passed as arguments: integers, reals
(IEEE!), and booleans are passed as the 32 bit bitpatterns
corresponding to their values; strings are passed as the 32 bit
address of their contents with the length as the following 32 bit
integer. (N.B. PostScript strings are terminated by length; there
is no terminating null unless the program puts one there. The user
function may not go beyond the string length!)
<hookadr> and <msgadr> are integers that are used as 32 bit memory
address. If no <msgadr> is needed, just use 0. These addresses should
be passed to the interpreter via the PSintstring() function in full
PostScript notation like "/hookadr 16#780ab44 def" to be used by
special PostScript code. It is advisable to put them into special,
private dictionaries.
The argument values passed are put into an array of 32 bit values
which is passed as "objectptr" to the Hook. The return value will be
put on the operand stack as <resint> and any changes to numeric values
in the 32 bit array will be put back into the args on the operand
stack. The Hook may change string contents within the address and
length passed to it.
As an example assume this calling sequence:
mark 1 string1 2.5 4 string2 false hookadr 0 @calluserhook
The 32 bit array passed to the hook as object will have these
contents:
array[0]: 32 int 1
array[1]: string1: address
array[2]: string1: length
array[3]: IEEE float 2.5
array[4]: 32 int 4
array[5]: string2: address
array[6]: string2: length
array[7]: 0
If the hook function changes array[0] to 3, array[7] to 1, and returns
-1, the resulting operand stack will contain these values:
mark 3 string1 2.5 4 string2 true -1
Changing a string address or length should not be tried. If results
are not needed, a cleartomark will get rid of them easily.
There should not be any assumptions made about internal representation
of objects. For booleans, only 0 and 1 should be used.
N.B. PSintstring() is not guaranteed to work recursively. So calling
it from the hook is not a good idea. The Hook is called on the
interpreters context. If a local near data section is needed, the Hook
function is responsible for setting up A4, e.g. from hook->h_Data.
Standard rules for saving registers apply. Do not assume that A4
contains anything useful!
Calling External Functions with @callextfunc
============================================
The original "callextfunc" operator of post.library <= V1.7 is no
longer supported even though it is still available in disguise as
"@callextfunc". Use of this operator is strongly discouraged as it
might lure you into making assumptions about internal HWGPOST data
representations. It is only here for limited backwards compatibility.
Do not use it for new code!
If you supply an external function table your PostScript program can
call the functions within it by the "@callextfunc" operator. The
contents of the table are the addresses of the function entry points.
The functions must have standard (Lattice, non-registerised) C
compatible calling sequences. They must not assume any useful value in
register A4 on entry, and must preserve A4 and the other C registers
on exit.
Unlike with post.library <= 1.7 there is additional information given,
though. To help identify calls from multiple activations, the activation
record address is also passed in A0 and the userdata pointer in A1.
Only certain PostScript objects may be passed as arguments: integers
reals and booleans are passed as the 32 bit bitpatterns corresponding
to their values; arrays and strings are passed as the 32 bit address
of their contents - if the length is required it must be passed
separately. (N.B. PostScript strings are terminated by length; there
is no terminating null unless the program puts one there.)
It is theoretically possible to pass arbitrary objects by including
them within an array, but then you would need to know their PostScript
representation. As the representation has been changed thoroughly for
HWGPOST and will continue to change in the future, this "feature" is
of no use at all!
The "@callextfunc" operator is only inserted into the system
dictionary if a function table is present. So you will not find it if
you attempt to execute it from the standard user interface.
Library Entry points
====================
Prototypes and pragmas for the entry points are defined in the header
file.
Create a PostScript activation
------------------------------
D0:int arec = PScreateact(A1:struct PSparm *parm)
The result is the address of the new activation record. If the
activation fails an error code is returned instead - zero if the
interpreter failed to start at all because there was insufficient free
memory, or an interpreter error code if there was an error during
initialisation. Otherwise the result is the address of the activation
record. The result is always returned as an int. If is is greater
than errmax then the activation was successful, and the value is an
address; otherwise the activation failed, and the result is zero or an
error code.
Delete a PostScript activation
------------------------------
VOID PSdeleteact(A0:APTR arec)
The activation record is deleted and the associated memory is freed.
Interpret a string or file
--------------------------
D0:int errnum = PSintstring(A0:APTR arec, A1:char *string,
D0:int length, D1:int flags)
Flag bits:
PSFLAGSTRING, PSFLAGGFILE, PSFLAGRUNSTDIN
If PSFLAGSTRING is set, the contents of the string are
interpreted as PostScript source. Starting with V23.1 of
post.library, strings are treated like files internally
and they can have a maximum length of 2GB-1. If you pass
in -1 as length, the string will be assumed to be NUL
terminated. Other negative length values shoudl not be
passed in.
If the flag PSFLAGFILE is set, the string is a file name.
Then the file's contents are interpreted.
Starting with version 22.27, you can use PSFLAGRUNSTDIN to
make post.library set up the input stream %stdin that you
provided as currentfile.
If neither of these flag bits are set the string is ignored,
but the other flag bits still have their effects; if more than
one is set the result is undefined.
PSFLAGINTER
If PSFLAGINTER is set (when interpreting a file), the file is
considered to be interactive. The banner is printed, and the
interpreter prompts for each line of input from the file.
PSFLAGCLEAR
If PSFLAGCLEAR is set, then after interpretation the operand
stack is cleared and the dictionary stack is popped until only
the system and user dictionaries remain. The execution stack
is emptied, too.
PSFLAGSAVE
If PSFLAGSAVE is set, job server behaviour is set up for the
current job only. It is functionally equivalent to
(PSFLAGSTARTJOBSERVER| PSFLAGENDJOBSERVER) but you shouldn't
use the job server flags instead if you really want
PSFLAGSAVE.
IMPORTANT: For running setup files like "init.ps", you should
not use PSFLAGSAVE or job server flags!
PSFLAGSTARTJOBSERVER, PSFLAGENDJOBSERVER
With PSFLAGSTARTJOBSERVER and PSFLAGENDJOBSERVER one can
create one job server run, spanning multiple invocations of
PSintstring(). The former forces a successful startjob with a
"false" operand before running the job, the latter forces a
successful startjob with a "true" operand after running the
job and clears out the execution stack and does some other
private things. These flags do not nest. If you think about
using them in a tricky way: Think again and ask _first_.
IMPORTANT: For running setup files like "init.ps", you should
not use PSFLAGSAVE or job server flags!
PSFLAGERASE
If PSFLAGERASE is set, then the page is erased. This happens
right at the end, after any vm restore, so the page is erased
taking into account the restored transfer function(s).
This routine is NOT guaranteed to recurse correctly; strange things or
crashes may happen if you try to call it from an external function
called from the same activation.
Signal an interrupt
-------------------
VOID PSsignalint(A0:APTR arec, D0:int flag)
This routine may be called to set an interrupt signal flag to notify
the interpreter of a special condition. The possible flag values are
defined in the header file postlib.h. You may or multiple bit flags
together. The interpreter tests these flags at the head of its main
loop, and also within certain potentially length operators (=, ==,
stack and pstack). If a flag is set it the interpreter will take
appropriate action immediately and automatically clear the
corresponding flag bit. You may safely call this routine at any time
during the life of the activation from any task or interrupt. It is
intended to be called from within your task's exception handler, if
the CTRL-C break signal is set. Unlike with post.library <= V1.7 it
is not possible to clear a flag once it has been set by calling
this function. Only the interpreter will clear a flag bit when it
is handled.
You may also call this function from the copypage callback with the
PSINTSIGF_KILL flag. This will make the interpreter skip the erasepage
command when doing a showpage, and allows you to obtain a generated
bitmap easily. You don't need a backup bitmap then. It is advisable of
course not to use PSFLAGERASE either in this case.
Signal a floating point error
-----------------------------
VOID PSsignalfpe(A0:APTR arec)
This routine is somewhat obsolete. It used to be the function to
call on a floating point trap and caused an immediate
undefinedresult error. Since HWGPOST V22.28, the interprer runs on
its own context though and there is no way for user code to see
a floating point trap that would be caused by this function. Which
in essence means that you may ONLY CALL THIS WITHIN A CALLBACK like
copypage or flushpage. Even then, PSerror(), which is
described below, may be a much better choice.
Error
-----
VOID PSerror(A0:APTR arec, D0:int errnum)
This routine is intended to be called from within your own flush or
copy page functions, to signal that an error ocurred. You can also
call it from an external function. You must not call it at any other
time; if you do, you will crash the machine. It calls the PostScript
error handler and never returns. The values for the error number are
defined in the header file. It is essential that you ensure that
you ONLY CALL THIS WITHIN A CALLBACK like copypage or flushpage.
Return a text string corresponding to an error name
---------------------------------------------------
D0:const char *str = PSerrstr(A0:int arec, D0:int errnum)
Converts a postscript error number to a text string. Returns NULL if
the number is out of range. This function may called from any task
while the activation record is valid.
Change device page
------------------
VOID PSsetdevice(A0:APTR arec, A1:struct PSdevice *page)
Note: While "setpagedevice" is not currently available, the effects
caused by PSsetdevice() are _very_ likely to change in many ways
when the time comes. If you feel that you rely on effects other
than simply replacing the device page buffer and dimensions,
CONTACT ME NOW.
Changes the device page buffer and dimensions. If the clip path is
still set to its initial value (the whole page) it is changed to match
the new page size; otherwise it is unchanged (and may therefore
possibly exceed the new page size). All the clip paths saved on the
graphics stack are similarly changed. The CTM at the topmost saved
graphics state (the one returned to by a "grestoreall" when there are
no active VM saves) is reset to match the new page size and density.
Otherwise the CTM is not affected; you will likely want to execute
"initmatrix" afterwards.
The interactions of this routine with the stack of saved graphics
states are complex, leading to unexpected behaviour unless you
understand exactly what is happening. So it is safest to think twice
about calling it and always call it when there are no save's or
gsave's active, and then to reinitialise the CTM immediately.
In other words: You better not use it. Stay away from it.
This routine should not be called from within a character build,
kerning, or imaging procedure.
Problems, Comments, and Bugs
============================
You will find my complete address in the header file "postlib.h".
Contact me if you have any questions or suggestions. Don't rely on
empirical programming. It is a lot faster and easier to ask than
wasting time with fiddling around.
Heinz Wrobel
<heinz@hwg.muc.de>
*** EOT ***